﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace USB2XXX
{
    class USB2SENT
    {
        //函数返回错误值宏定义
        public const int SENT_SUCCESS = (0);   ///<函数执行成功
        public const int SENT_ERR_NOT_SUPPORT = (-1);  ///<适配器不支持该函数
        public const int SENT_ERR_USB_WRITE_FAIL = (-2);  ///<USB写数据失败
        public const int SENT_ERR_USB_READ_FAIL = (-3);  ///<USB读数据失败
        public const int SENT_ERR_CMD_FAIL = (-4);  ///<命令执行失败
        public const int SENT_ERR_PARAMETER = (-7);  ///<函数参数传入有误
        public const int SENT_ERR_MSG_TYPE = (-8);  ///<当前函数不支持该消息类型

        //SENT主从模式
        public const byte SENT_MASTER = 1; ///<主机模式，用于模拟主节点发送数据
        public const byte SENT_SLAVE = 0; ///<从机模式，用于监控SENT主机发送出来的数据

        //SENT消息类型定义，该值在MsgType里面体现
        public const byte SENT_MSGTYPE_ERROR = 0; ///<错误帧，比如CRC错误，数据不完整等
        public const byte SENT_MSGTYPE_FAST = 1; ///<快速通道数据,数据存放在Data[0]~Data[7]里面，Status的高4位代表数据有效半字节数
        public const byte SENT_MSGTYPE_SLOW_SHORT = 2; ///<慢速通道，简短型串行信息,Data[0]为ID,Data[1]为数据
        public const byte SENT_MSGTYPE_SLOW_ENH1 = 3; ///<慢速通道，增强型串行信息,12位数据+8位ID,Data[0]为ID，Data[1]为高4位数据,Data[2]为低8位数据
        public const byte SENT_MSGTYPE_SLOW_ENH2 = 4; ///<慢速通道，增强型串行信息,16位数据+4位ID,Data[0]为ID，Data[1]为高8位数据,Data[2]为低8位数据


        //SENT总线空闲电平
        public const byte SENT_IDLE_HIGH = 1; ///<总线空闲时为高电平，数据输出低电平脉冲
        public const byte SENT_IDLE_LOW = 0; ///<总线空闲时为低电平，数据输出高电平脉冲

        //SENT初始化结构定义
        public struct SENT_CONFIG
        {
            public byte TicksTimeUs;    ///<Ticks时间，单位为us，一般为3
            public byte MasterMode;     ///<0-从机模式，用于监控SENT总线数据，1-主机模式，用于发送SENT总线数据
            public byte LowTicks;       ///<低电平输出Ticks数，低电平输出时间=TicksTimeUs*LowTicks，推荐设置为5
            public byte PausePulseTicks;///<暂停脉冲数，0-不输出，1~64对应12Ticks~768Ticks
            public byte NibbleNum;      ///<快速通道半字节数，不包含CRC，从机模式若是0则自动匹配，主机模式Status高4位代表要发送的有效半字节数
            public byte IdleLevel;      ///<总线空闲状态，0-空闲低电平，1-空闲高电平
        }

        //SENT帧结构定义
        public struct SENT_MSG
        {
            public UInt32 Timestamp;      ///<接收到信息帧时的时间标识，从SENT控制器初始化开始计时，单位为100us。发送数据时为帧间隔时间，单位为ms
            public byte TimestampHigh;  ///<接收数据时为时间戳高位,发送帧时为该帧发送次数
            public byte Status;         ///<高4位代表Data有效字节数，低4位代表Status
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
            public byte[] Data;        ///<根据帧类型存储不同的数据
            public byte crc;            ///<MsgType若为增强型串行信息，则是6bit有效CRC，其他的为4bit有效CRC，bit7-当前帧为错误帧
            public byte MsgType;        ///<帧类型，具体可以参考帧类型定义
        }
        /**
         * @brief 初始化配置SENT总线，必须调用，否则无法正常工作
         * @param DevHandle 设备号，通过调用 @ref USB_ScanDevice 获取
         * @param Channel SENT通道号，0-SENT1，1-SENT2，2-SENT3，3-SENT4，SENT总线在硬件上是跟LIN总线共用的
         * @param[in] pConfig 初始化结构体，可以参考 @ref SENT初始化结构定义 查看参数详情
         * @return 函数执行状态
         * @retval =0 函数执行成功
         * @retval !=0 函数执行失败
         */
        [DllImport("USB2XXX.dll")]
        public static extern Int32  SENT_Init(Int32 DevHandle,Byte Channel, ref SENT_CONFIG pConfig);

        /**
         * @brief  主机模式下手动发送SENT消息
         * @param  DevHandle 设备号，通过调用 @ref USB_ScanDevice 获取
         * @param  Channel SENT通道号，0-SENT1，1-SENT2，2-SENT3，3-SENT4，SENT总线在硬件上是跟LIN总线共用的
         * @param[in]  pSentMsg SENT消息帧指针
         * @param  MsgNum 发送的SENT消息帧数，不能大于64帧
         * @return 函数执行状态
         * @retval =0 函数执行成功
         * @retval !=0 函数执行失败
         */
        [DllImport("USB2XXX.dll")]
        public static extern Int32  SENT_SendMsg(Int32 DevHandle, Byte Channel, SENT_MSG[] pSentMsg, UInt32 MsgNum);

        /**
         * @brief  设置并启动SENT快速通道帧发送列表
         * @param  DevHandle 设备号，通过调用 @ref USB_ScanDevice 获取
         * @param  Channel SENT通道号，0-SENT1，1-SENT2，2-SENT3，3-SENT4，SENT总线在硬件上是跟LIN总线共用的
         * @param  pSentMsg SENT快速通道消息帧指针
         * @param  MsgNum 发送的SENT消息帧数，不能大于64帧
         * @param  SendTimes 列表循环发送次数，若设置为0xFFFFFFFF则一直循环发送列表，直到调用 @ref SENT_StopFastMsgTable 函数为止
         * @return 函数执行状态
         * @retval =0 函数执行成功
         * @retval !=0 函数执行失败
         */
        [DllImport("USB2XXX.dll")]
        public static extern Int32  SENT_StartFastMsgTable(Int32 DevHandle, Byte Channel, SENT_MSG[] pSentMsg, UInt32 MsgNum, UInt32 SendTimes);

        /**
         * @brief  停止正在发送的SENT帧列表
         * @param  DevHandle 设备号，通过调用 @ref USB_ScanDevice 获取
         * @param  Channel SENT通道号，0-SENT1，1-SENT2，2-SENT3，3-SENT4，SENT总线在硬件上是跟LIN总线共用的
         * @return 函数执行状态
         * @retval =0 函数执行成功
         * @retval !=0 函数执行失败
         */
        [DllImport("USB2XXX.dll")]
        public static extern Int32  SENT_StopFastMsgTable(Int32 DevHandle, Byte Channel);

        /**
         * @brief  设置并启动SENT慢速通道帧发送列表，调用该函数后数据不会立即发送，它是在发送快速数据的时候才通过Status域发送，所以需要发送慢速通道帧数据，需要同时启动快速帧发送列表
         * @param  DevHandle 设备号，通过调用 @ref USB_ScanDevice 获取
         * @param  Channel SENT通道号，0-SENT1，1-SENT2，2-SENT3，3-SENT4，SENT总线在硬件上是跟LIN总线共用的
         * @param  pSentMsg SENT慢速通道消息帧指针
         * @param  MsgNum 发送的SENT消息帧数，不能大于64帧
         * @param  SendTimes 列表循环发送次数，若设置为0xFFFFFFFF则一直循环发送列表，直到调用 @ref SENT_StopSlowMsgTable 函数为止
         * @return 
         */
        [DllImport("USB2XXX.dll")]
        public static extern Int32 SENT_StartSlowMsgTable(Int32 DevHandle, Byte Channel, SENT_MSG[] pSentMsg, UInt32 MsgNum, UInt32 SendTimes);

        /**
         * @brief  停止正在发送的SENT帧列表
         * @param  DevHandle 设备号，通过调用 @ref USB_ScanDevice 获取
         * @param  Channel SENT通道号，0-SENT1，1-SENT2，2-SENT3，3-SENT4，SENT总线在硬件上是跟LIN总线共用的
         * @return 函数执行状态
         * @retval =0 函数执行成功
         * @retval !=0 函数执行失败
         */
        [DllImport("USB2XXX.dll")]
        public static extern Int32  SENT_StopSlowMsgTable(Int32 DevHandle, Byte Channel);

        /**
         * @brief 主机模式获取已发成功发送出去的帧，从机模式获取监控到的帧
         * @param DevHandle 设备号，通过调用 @ref USB_ScanDevice 获取
         * @param Channel SENT通道号，0-SENT1，1-SENT2，2-SENT3，3-SENT4，SENT总线在硬件上是跟LIN总线共用的
         * @param pSentMsg 存储SENT帧缓冲区指针，该缓冲区不能小于64，否则可能会出现缓冲区溢出导致程序异常闪退
         * @return 成功获取到的SENT消息帧数
         * @retval <0 函数执行失败
         */
        [DllImport("USB2XXX.dll")]
        public static extern Int32 SENT_GetMsg(Int32 DevHandle, Byte Channel, IntPtr pSentMsg);
        /**
         * @brief  获取SENT起始时间戳，该时间戳可以转换成实际的时间
         * @param  DevHandle 设备号，通过调用 @ref USB_ScanDevice 获取
         * @param  Channel SENT通道号，0-SENT1，1-SENT2，2-SENT3，3-SENT4
         * @return SENT起始时间戳
         * @retval <0 函数调用失败
         */
        [DllImport("USB2XXX.dll")]
        public static extern Int64 SENT_GetStartTime(Int32 DevHandle, Byte Channel);

        /**
         * @brief  复位时间戳，复位后起始时间戳为当前时间
         * @param  DevHandle 设备号，通过调用 @ref USB_ScanDevice 获取
         * @param  Channel SENT通道号，0-SENT1，1-SENT2，2-SENT3，3-SENT4
         * @return 函数执行状态
         * @retval <0 函数调用失败
         */
        [DllImport("USB2XXX.dll")]
        public static extern Int32 SENT_ResetStartTime(Int32 DevHandle, Byte Channel);
    }
}
